"""
图片数据模型
目的：存储图片文件的元数据信息，关联到用户、文章、打卡等业务对象
职责：管理图片的基本信息、访问权限和使用场景
"""

from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, Text, ForeignKey, Index
from sqlalchemy.orm import relationship
from app.config.database import Base


class Image(Base):
    """
    图片模型类
    目的：记录上传图片的元数据，包括来源、用途和访问信息
    职责：管理图片生命周期，提供图片查询和统计功能
    """

    __tablename__ = 'images'

    # 主键ID
    id = Column(Integer, primary_key=True, autoincrement=True, comment='图片ID')

    # 图片基本信息（对应数据库实际字段）
    filename = Column(String(255), nullable=False, comment='文件名称')
    file_path = Column(String(500), nullable=False, comment='文件存储路径（MinIO对象名称）')
    file_size = Column(Integer, nullable=False, comment='文件大小（字节）')
    file_type = Column(String(50), nullable=False, comment='文件类型（MIME类型）')
    width = Column(Integer, nullable=True, comment='图片宽度')
    height = Column(Integer, nullable=True, comment='图片高度')

    # 上传者信息
    user_id = Column(Integer, ForeignKey('users.id'), nullable=False, comment='上传用户ID')

    # 图片用途分类（usage_type: 1-头像, 2-文章配图, 3-打卡图片, 4-评论图片, 5-其他）
    usage_type = Column(Integer, nullable=False, default=1, comment='用途类型：1-其他, 2-头像, 3-文章配图, 4-打卡图片, 5-评论图片')

    # 状态信息
    status = Column(Integer, default=1, nullable=False, comment='状态：1-正常、0-已删除')

    # 时间戳
    created_at = Column(DateTime, default=datetime.now, nullable=False, comment='创建时间')

    # 关联关系
    user = relationship('User', backref='images')

    # 索引
    __table_args__ = (
        Index('idx_images_user_id', 'user_id'),
        Index('idx_images_usage_type', 'usage_type'),
        Index('idx_images_status', 'status'),
        Index('idx_images_created_at', 'created_at'),
    )

    def to_dict(self, include_user: bool = False, include_url: bool = True) -> dict:
        """
        将图片对象转换为字典格式

        Args:
            include_user: 是否包含用户信息
            include_url: 是否生成访问URL

        Returns:
            dict: 图片信息字典
        """
        from app.services.minio_service import MinioService

        data = {
            'id': self.id,
            'filename': self.filename,
            'file_path': self.file_path,
            'file_size': self.file_size,
            'file_type': self.file_type,
            'width': self.width,
            'height': self.height,
            'usage_type': self.usage_type,
            'usage_type_label': self.get_usage_type_label(self.usage_type),
            'user_id': self.user_id,
            'status': self.status,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
        }

        # 生成访问URL
        if include_url:
            try:
                minio_service = MinioService()
                # 根据usage_type判断文件类型
                file_type = 'images'
                url = minio_service.get_presigned_url(self.file_path, file_type, expires=3600)
                data['url'] = url
            except Exception as e:
                data['url'] = None

        # 添加用户信息（如果需要）
        if include_user and self.user:
            data['user'] = {
                'id': self.user.id,
                'username': self.user.username,
                'nickname': self.user.nickname
            }

        return data

    @staticmethod
    def get_usage_type_label(usage_type: int) -> str:
        """
        获取用途类型的中文标签

        Args:
            usage_type: 用途类型代码

        Returns:
            str: 中文标签
        """
        labels = {
            1: '其他图片',
            2: '用户头像',
            3: '文章配图',
            4: '打卡图片',
            5: '评论图片'
        }
        return labels.get(usage_type, '未知类型')

    @staticmethod
    def get_file_type_label(file_type: str) -> str:
        """
        获取文件类型的中文标签

        Args:
            file_type: MIME类型

        Returns:
            str: 中文标签
        """
        labels = {
            'image/jpeg': 'JPEG图片',
            'image/jpg': 'JPG图片',
            'image/png': 'PNG图片',
            'image/gif': 'GIF图片',
            'image/webp': 'WebP图片',
            'image/bmp': 'BMP图片'
        }
        return labels.get(file_type, '未知格式')